import { promises as fs } from "fs";
import { existsSync } from "node:fs";
import path from "path";
import { rimraf } from "rimraf";

import { registryBlocks } from "@dotui/registry/blocks/registry";
import { iconLibraries, registryIcons } from "@dotui/registry/icons/registry";

async function buildBlocks() {
  const TARGET_PATH = path.join(process.cwd(), "src/blocks/__blocks__.tsx");
  await rimraf(TARGET_PATH);

  let index = `/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
// This file is autogenerated by scripts/build-registry.ts
// Do not edit this file directly.
import * as React from "react"

export const Index: Record<
  string,
  {
    files: string[];
    component: React.LazyExoticComponent<React.ComponentType<object>>;
  }
> = {
`;

  for (const block of registryBlocks) {
    const blockFiles =
      block.files?.map((file) => {
        const filePath = typeof file === "string" ? file : file.path;
        return filePath;
      }) || [];

    let componentPath = `@dotui/registry/blocks/${block.name}`;

    if (block.files && block.files.length > 0) {
      const files = block.files.map((file) =>
        typeof file === "string" ? { type: "registry:page", path: file } : file,
      );
      if (files?.length && files[0]) {
        const firstFilePath = files[0].path.replace(/\.tsx?$/, "");
        componentPath = `@dotui/registry/${firstFilePath}`;
      }
    }

    index += `
  "${block.name}": {
    files: ${JSON.stringify(blockFiles)},
    component: React.lazy(async () => {
      const mod = await import("${componentPath}")
      const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name
      return { default: mod.default || mod[exportName] }
    })
  },`;
  }

  index += `
}
`;

  await fs.writeFile(TARGET_PATH, index, "utf8");
}

async function processDirectory(
  dirPath: string,
  relativePath: string,
  index: string[],
): Promise<void> {
  const entries = await fs.readdir(dirPath, { withFileTypes: true });

  for (const entry of entries) {
    if (entry.isFile() && entry.name.endsWith(".tsx")) {
      const demoName = `${relativePath}/${entry.name.replace(".tsx", "")}`;
      const demoPath = `@dotui/registry/ui/${relativePath}/${entry.name.replace(".tsx", "")}`;
      const filePath = `ui/${relativePath}/${entry.name}`;

      index.push(`
  "${demoName}": {
    files: ["${filePath}"],
    component: React.lazy(() => import("${demoPath}")),
  },`);
    } else if (entry.isDirectory()) {
      const subDirPath = path.join(dirPath, entry.name);
      const subRelativePath = `${relativePath}/${entry.name}`;
      await processDirectory(subDirPath, subRelativePath, index);
    }
  }
}

async function buildDemos() {
  const targetPath = path.join(process.cwd(), "src/ui/__demos__.tsx");

  let index = `// This file is autogenerated by scripts/build-registry.ts
// Do not edit this file directly.
import * as React from "react"

export const Index: Record<
  string,
  {
    files: string[];
    component: React.LazyExoticComponent<React.ComponentType<object>>;
  }
> = {
`;

  const sourcePath = path.join(process.cwd(), "src/ui");
  const componentFolders = await fs.readdir(sourcePath);

  const indexEntries: string[] = [];

  for (const componentFolder of componentFolders) {
    const componentPath = path.join(sourcePath, componentFolder);
    const stats = await fs.stat(componentPath);

    if (!stats.isDirectory()) continue;

    const demosPath = path.join(componentPath, "demos");

    if (!existsSync(demosPath)) continue;

    await processDirectory(demosPath, `${componentFolder}/demos`, indexEntries);
  }

  index += indexEntries.join("");

  index += `
}
`;

  const outputDir = path.dirname(targetPath);
  await fs.mkdir(outputDir, { recursive: true });

  await fs.writeFile(targetPath, index, "utf8");
}

async function buildIcons() {
  const targetPath = path.join(process.cwd(), "src/icons/__icons__.tsx");

  const iconKeys = Object.keys(registryIcons);

  const iconExports = iconKeys
    .map((iconKey) => {
      const iconMapping = registryIcons[iconKey];
      if (!iconMapping) {
        throw new Error(`Icon mapping not found for: ${iconKey}`);
      }

      const libraryMappings = iconLibraries
        .map((library) => {
          const iconName = iconMapping[library.name];
          if (!iconName) {
            throw new Error(
              `Icon "${iconKey}" not found for library "${library.name}"`,
            );
          }

          if (library.name === "lucide") {
            return `  lucide: Lucide.${iconName}`;
          } else {
            return `  ${library.name}: React.lazy(() => import("${library.import}").then(mod => ({ default: mod.${iconName} })))`;
          }
        })
        .join(",\n");

      return `export const ${iconKey} = createIcon({
${libraryMappings}
});`;
    })
    .join("\n\n");

  const content = `// This file is autogenerated by scripts/build-registry.ts
// Do not edit this file directly.
"use client";

import * as React from "react";
import * as Lucide from "lucide-react";
import { createIcon } from "../_helpers/create-icon";

${iconExports}
`;

  const outputDir = path.dirname(targetPath);
  await fs.mkdir(outputDir, { recursive: true });

  await fs.writeFile(targetPath, content, "utf8");
}

async function main() {
  console.log("🔨 Building registry...");

  try {
    await buildBlocks();
    await buildDemos();
    await buildIcons();
    console.log("✅ Registry built successfully!");
  } catch (error) {
    console.error("❌ Error building registry:", error);
    process.exit(1);
  }
}

main();
